﻿// uxMapTree.cpp: 实现文件
//

#include "stdafx.h"
#include "resource.h"
#include "uxMapTree.h"


#define DRAG_DELAY 60
// uxMapTree

#define	MAPTREE_MAP		0
#define	MAPTREE_POINT	1
#define	MAPTREE_LINE	2
#define	MAPTREE_POLYGON	3
#define	MAPTREE_TIN		4
#define	MAPTREE_RASTER	5
#define	MAPTREE_TABLE	6
#define	MAPTREE_GROUP	6

IMPLEMENT_DYNAMIC(uxMapTree, CTreeCtrl)

uxMapTree::uxMapTree()
{
	m_pMap = NULL;
	m_pDragImage = NULL;
	m_hItemDragS = NULL;
	m_hItemDragD = NULL;
	m_bDragging = FALSE;
}

uxMapTree::~uxMapTree()
{
	if (m_pDragImage)
	{
		delete m_pDragImage;
		m_pDragImage = NULL;
	}
}


BEGIN_MESSAGE_MAP(uxMapTree, CTreeCtrl)
	ON_WM_CREATE()
	ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, &uxMapTree::OnTvnBeginrdrag)					  
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_TIMER()
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, &uxMapTree::OnTvnBegindrag)
	ON_NOTIFY_REFLECT(NM_CLICK, &uxMapTree::OnNMClick)
	ON_NOTIFY_REFLECT(NM_RCLICK, &uxMapTree::OnNMRClick)
END_MESSAGE_MAP()



// uxMapTree 消息处理程序




int uxMapTree::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	BOOL ret = m_imageList.Create(IDB_UX_MAPTREE_BITMAP, 16, 112, RGB(255, 255, 255));
	
	if (ret)
	{
		CImageList* pList = SetImageList(&m_imageList, TVSIL_NORMAL);
	}
	
	HTREEITEM  hRoot = InsertItem(_T("地图"), 0, 0);
	SetItemState(hRoot, INDEXTOSTATEIMAGEMASK(0), TVIS_STATEIMAGEMASK);
	SetItemData(hRoot, 0);
	SetCheck(hRoot, 1);
	Expand(hRoot, TVE_EXPAND);

	return 0;
}


void uxMapTree::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码

	//如果是无意拖动，则放弃操作
	if ((GetTickCount() - m_dwDragStart) < DRAG_DELAY)
	{
		return;
	}

	m_hItemDragS = pNMTreeView->itemNew.hItem;
	m_hItemDragD = NULL;

	//得到用于拖动时显示的图象列表
	m_pDragImage = CreateDragImage(m_hItemDragS);
	if (!m_pDragImage)
	{
		return;
	}

	m_bDragging = TRUE;
	m_pDragImage->BeginDrag(0, CPoint(8, 8));
	CPoint pt = pNMTreeView->ptDrag;
	ClientToScreen(&pt);
	m_pDragImage->DragEnter(this, pt); //"this"将拖动操作限制在该窗口
	SetCapture();

	m_nScrollTimerID = SetTimer(2, 40, NULL);

	*pResult = 0;
}

void uxMapTree::OnTvnBeginrdrag(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码

	

	*pResult = 0;
}

void uxMapTree::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//处理无意拖曳
	m_dwDragStart = GetTickCount();

	CTreeCtrl::OnLButtonDown(nFlags, point);
}


//void uxMapTree::OnLButtonUp(UINT nFlags, CPoint point)
//{
//	// TODO: 在此添加消息处理程序代码和/或调用默认值
//
//	CTreeCtrl::OnLButtonUp(nFlags, point);
//
//	if (m_bDragging)
//	{
//		m_bDragging = FALSE;
//		CImageList::DragLeave(this);
//		CImageList::EndDrag();
//		ReleaseCapture();
//		delete m_pDragImage;
//
//		SelectDropTarget(NULL);
//
//		if (m_hItemDragS == m_hItemDragD)
//		{
//			KillTimer(m_nScrollTimerID);
//			return;
//		}
//
//		CString strS = GetItemText(m_hItemDragD);
//		CString strD = GetItemText(m_hItemDragS);
//
//		Expand(m_hItemDragD, TVE_EXPAND);
//		HTREEITEM htiParent = m_hItemDragD;
//
//		//如果是由父节点拖向子节点
//		while ((htiParent = GetParentItem(htiParent)) != NULL)
//		{
//			if (htiParent == m_hItemDragS)
//			{
//				//建立一个临时节点以完成操作
//				HTREEITEM htiNewTemp = CopyBranch(m_hItemDragS, NULL, TVI_LAST);
//				HTREEITEM htiNew = CopyBranch(htiNewTemp, m_hItemDragD, TVI_LAST);
//				DeleteItem(htiNewTemp);
//				SelectItem(htiNew);
//				KillTimer(m_nScrollTimerID);
//				return;
//			}
//		}
//
//		HTREEITEM htiNew = CopyBranch(m_hItemDragS, m_hItemDragD, TVI_LAST);
//		DeleteItem(m_hItemDragS);
//		SelectItem(htiNew);
//		KillTimer(m_nScrollTimerID);
//	}
//}

void uxMapTree::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	TRACE0("OnLButton  Up  \n");

	CTreeCtrl::OnLButtonUp(nFlags, point);

	if (m_bDragging)
	{
		m_bDragging = FALSE;
		CImageList::DragLeave(this);
		CImageList::EndDrag();
		ReleaseCapture();
		if (m_pDragImage)
		{
			delete m_pDragImage;
			m_pDragImage = NULL;
		}
		

		SelectDropTarget(NULL);

		if (m_hItemDragS == m_hItemDragD)
		{
			KillTimer(m_nScrollTimerID);
			return;
		}

		CString strS = GetItemText(m_hItemDragS);
		CString strD = GetItemText(m_hItemDragD);

		Expand(m_hItemDragD, TVE_EXPAND);

		HTREEITEM hRoot = GetRootItem();
		if (hRoot == m_hItemDragD)
		{
			//如果是根节点，那个放在放在第一个子节点
			HTREEITEM htiNew = CopyBranch(m_hItemDragS, m_hItemDragD, TVI_FIRST);
			DeleteItem(m_hItemDragS);
			SelectItem(htiNew);
			KillTimer(m_nScrollTimerID);


		}
		else
		{
			HTREEITEM htiNew = CopyBranch(m_hItemDragS, hRoot, m_hItemDragD);//TVI_LAST);
			//HTREEITEM htiNew = CopyBranch(m_hItemDragS, m_hItemDragD, TVI_LAST);
			DeleteItem(m_hItemDragS);
			SelectItem(htiNew);
			KillTimer(m_nScrollTimerID);
		}
	}
}

void uxMapTree::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	HTREEITEM hItem;
	UINT flags;

	//检测鼠标敏感定时器是否存在,如果存在则删除,删除后再定时
	if (m_nHoverTimerID)
	{
		KillTimer(m_nHoverTimerID);
		m_nHoverTimerID = 0;
	}
	m_nHoverTimerID = SetTimer(1, 800, NULL); //定时为 0.8 秒则自动展开
	m_HoverPoint = point;

	if (m_bDragging)
	{
		CPoint pt = point;
		CImageList::DragMove(pt);

		//鼠标经过时高亮显示
		CImageList::DragShowNolock(false); //避免鼠标经过时留下难看的痕迹
		if ((hItem = HitTest(point, &flags)) != NULL)
		{
			SelectDropTarget(hItem);
			m_hItemDragD = hItem;
		}
		CImageList::DragShowNolock(true);

		//当条目被拖曳到左边缘时，将条目放在根下
		CRect rect;
		GetClientRect(&rect);
		if (point.x < rect.left + 20)
			m_hItemDragD = NULL;
	}

	CTreeCtrl::OnMouseMove(nFlags, point);
}


void uxMapTree::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CTreeCtrl::OnLButtonDblClk(nFlags, point);
}


void uxMapTree::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CTreeCtrl::OnRButtonDown(nFlags, point);
}


void uxMapTree::OnRButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CTreeCtrl::OnRButtonUp(nFlags, point);
}


void uxMapTree::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nIDEvent == m_nHoverTimerID)
	{
		KillTimer(m_nHoverTimerID);
		m_nHoverTimerID = 0;
		HTREEITEM trItem = 0;
		UINT uFlag = 0;
		trItem = HitTest(m_HoverPoint, &uFlag);
		if (trItem && m_bDragging)
		{
			SelectItem(trItem);
			Expand(trItem, TVE_EXPAND);
		}
	}
	//处理拖曳过程中的滚动问题
	else if (nIDEvent == m_nScrollTimerID)
	{
		m_TimerTicks++;
		CPoint pt;
		GetCursorPos(&pt);
		CRect rect;
		GetClientRect(&rect);
		ClientToScreen(&rect);

		HTREEITEM hItem = GetFirstVisibleItem();

		if (pt.y < rect.top + 10)
		{
			//向上滚动
			int slowscroll = 6 - (rect.top + 10 - pt.y) / 20;
			if (0 == (m_TimerTicks % ((slowscroll > 0) ? slowscroll : 1)))
			{
				CImageList::DragShowNolock(false);
				SendMessage(WM_VSCROLL, SB_LINEUP);
				SelectDropTarget(hItem);
				m_hItemDragD = hItem;
				CImageList::DragShowNolock(true);
			}
		}
		else if (pt.y > rect.bottom - 10)
		{
			//向下滚动
			int slowscroll = 6 - (pt.y - rect.bottom + 10) / 20;
			if (0 == (m_TimerTicks % ((slowscroll > 0) ? slowscroll : 1)))
			{
				CImageList::DragShowNolock(false);
				SendMessage(WM_VSCROLL, SB_LINEDOWN);
				int nCount = GetVisibleCount();
				for (int i = 0; i < nCount - 1; i++)
					hItem = GetNextVisibleItem(hItem);
				if (hItem)
					SelectDropTarget(hItem);
				m_hItemDragD = hItem;
				CImageList::DragShowNolock(true);
			}
		}
	}
	else
	{
		CTreeCtrl::OnTimer(nIDEvent);
	}
}

//拷贝条目
HTREEITEM uxMapTree::CopyItem(HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
	TV_INSERTSTRUCT tvstruct;
	HTREEITEM hNewItem;
	CString sText;

	//得到源条目的信息
	tvstruct.item.hItem = hItem;
	tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
	GetItem(&tvstruct.item);
	sText = GetItemText(hItem);
	tvstruct.item.cchTextMax = sText.GetLength();
	tvstruct.item.pszText = sText.LockBuffer();

	//将条目插入到合适的位置
	tvstruct.hParent = htiNewParent;
	tvstruct.hInsertAfter = htiAfter;
	tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
	hNewItem = InsertItem(&tvstruct);
	sText.ReleaseBuffer();

	//限制拷贝条目数据和条目状态
	SetItemData(hNewItem, GetItemData(hItem));
	SetItemState(hNewItem, GetItemState(hItem, TVIS_STATEIMAGEMASK), TVIS_STATEIMAGEMASK);

	return hNewItem;
}

//拷贝分支
HTREEITEM uxMapTree::CopyBranch(HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter)
{
	HTREEITEM hChild;
	HTREEITEM hNewItem = CopyItem(htiBranch, htiNewParent, htiAfter);
	hChild = GetChildItem(htiBranch);

	while (hChild != NULL)
	{
		CopyBranch(hChild, hNewItem, htiAfter);
		hChild = GetNextSiblingItem(hChild);
	}

	return hNewItem;
}


int	uxMapTree::AddLayer(u::Layer* pLayer, ux_uint type)
{
	HTREEITEM hRoot = this->GetRootItem();
	int layerIcon = GetLayerIcon(pLayer);
	ux_uint ltype = pLayer->GetType();

	// 添加当前图层节点
	HTREEITEM hGroup = this->InsertItem(pLayer->GetName(), layerIcon, layerIcon, hRoot);
	SetCheck(hGroup, pLayer->IsVisible() ? TRUE : FALSE);
	SetCheck(hRoot, 1);
	// 设置图层节点的附属ItemData信息
	uxLayerNodeItemData* pItemData = new uxLayerNodeItemData(
											pLayer,
											type,
											true
										);
	SetItemData(hGroup, (DWORD_PTR)pItemData);

	// 若当前节点是Group图层，则该图层下面包含子图层，需要将子图层作为当前GroupLayer的子节点
	// 调用U_LAYER_MAIN_TYPE宏，计算图层的主类型
	if (U_LAYER_MAIN_TYPE(ltype) == U_LAYER_GROUP)
	{	
		u::GroupLayer* pGroupLayer = (u::GroupLayer*)pLayer;
		int count = pGroupLayer->GetCount();
		for (int i = 0; i < count; i++)
		{
			u::Layer* psubLayer = pGroupLayer->GetLayer(i);
			if (psubLayer != NULL)
			{
				HTREEITEM hLayer = this->InsertItem(psubLayer->GetName(), 1, 1, hGroup);
				SetCheck(hLayer, psubLayer->IsVisible() ? TRUE : FALSE);

				// 生成子图层类型
				ux_uint subtype = 0x0100 | psubLayer->GetType();
				// 设置图层节点的附属ItemData信息
				uxLayerNodeItemData* pItemData = new uxLayerNodeItemData(
													psubLayer,
													subtype,	//type,
													false		//子图层不允许单独关闭
												);
				SetItemData(hLayer, (DWORD_PTR)pItemData);
			}
		}
		Expand(hGroup, TVE_EXPAND);
	}

	Expand(hRoot, TVE_EXPAND);

	return 0;
}

int	uxMapTree::GetLayerIcon(u::Layer* pLayer)
{
	ux_uint type = pLayer->GetType();
	switch (type)
	{
	//case u::layerVector:
	case U_LAYER_FEATURE:
	{
		u::FeatureLayer* pFeatureLayer = static_cast<u::FeatureLayer*>(pLayer);
		OGRwkbGeometryType geomType = pFeatureLayer->GetGeometryType();
		switch (geomType)
		{
		case wkbPoint:
		case wkbPoint25D:
		case wkbMultiPoint:
		case wkbMultiPoint25D:
			return MAPTREE_POINT;
		case wkbLineString:
		case wkbLineString25D:
		case wkbMultiLineString:
		case wkbMultiLineString25D:
			return MAPTREE_LINE;
		case wkbPolygon:
		case wkbPolygon25D:
		case wkbMultiPolygon:
		case wkbMultiPolygon25D:
			return MAPTREE_POLYGON;
		}
	}
	break;
	case U_LAYER_RASTER:
	{
		return MAPTREE_RASTER;
	}
	break;
	case U_LAYER_GROUP:
	{
		return MAPTREE_GROUP;
	}
	break;

	case U_LAYER_NONE:
	{

	}break;
	}

	return MAPTREE_MAP;
}

void uxMapTree::Attach(u::Map* pMap)
{
	m_pMap = pMap;
}

void uxMapTree::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码

	*pResult = 0;
}


void uxMapTree::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
}

#define	U_LAYER_NONE		0x0000
#define	U_LAYER_FEATURE		0x0001
#define	U_LAYER_RASTER		0x0002
#define	U_LAYER_GROUP		0x0003
#define	U_LAYER_RASTERSET	0x0103
//获取图层主类型
#define	U_LAYER_MAIN_TYPE(t) ((t)&(0x00FF))

BOOL uxMapTree::SetVisible(HTREEITEM hItem)
{
	BOOL visible = !GetCheck(hItem);
	HTREEITEM hRoot = GetRootItem();
	if (hItem == hRoot)
	{
		// 选中了Map节点
		if (m_pMap)
		{
			m_pMap->SetVisible(visible);
		}
	}
	else
	{
		// 选中了Layer节点
		uxLayerNodeItemData* pItemData = NULL;
		pItemData = (uxLayerNodeItemData*)GetItemData(hItem);
		if (pItemData)
		{
			u::Layer* pLayer = pItemData->GetLayer();
			if (pLayer)
			{
				pLayer->SetVisible(visible);
			}
		}
	}
	/*CString strText = GetItemText(hItem);
	
	ux_uint type = (ux_uint)GetItemData(hItem);
	switch (type)
	{
	case 0:
		m_pMap->SetVisible(visible);
		break;
	case U_LAYER_FEATURE:
	case U_LAYER_RASTER:
	case U_LAYER_GROUP:
	{
		u::Layer* pLayer = NULL;
		pLayer = m_pMap->GetLayer(strText);
		if (pLayer)
		{
			pLayer->SetVisible(visible);
		}
	}
	break;

	}*/
	return TRUE;
}

//BOOL uxMapTree::UpdateDateLayerVisible(HTREEITEM hItem)
//{
//	CString strText = GetItemText(hItem);
//	BOOL visible = !GetCheck(hItem);
//	ux_uint type = (ux_uint)GetItemData(hItem);
//	switch (type)
//	{
//	case 0:
//		m_pMap->SetVisible(visible);
//		break;
//	case U_LAYER_FEATURE:
//	case U_LAYER_RASTER:
//	case U_LAYER_GROUP:
//	{
//		u::Layer* pLayer = NULL;
//		pLayer = m_pMap->GetLayer(strText);
//		if (pLayer)
//		{
//			pLayer->SetVisible(visible);
//		}
//	}
//		break;
//
//	}
//	return TRUE;
//}